﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DynamicForm.Manager;
using DynamicForm.Models;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Text;
using System.Reflection;

namespace DynamicForm.Controllers
{
    public class PageController : Controller
    {
        public Dictionary<string, string> ContextData { get; set; }

        public ActionResult Compile()
        {
            using (DynoDataContext dataContext = new DynoDataContext())
            {
                List<FuncLibrary> funcs = dataContext.FuncLibraries.ToList();
                StringBuilder snippet = new StringBuilder();
                snippet.AppendLine("using System;");
                snippet.AppendLine("using System.Collections.Generic;");
                snippet.AppendLine("using System.Data;");
                snippet.AppendLine("using System.Web;");
                snippet.AppendLine("using DynamicForm.Manager;");
                snippet.AppendLine("using DynamicForm.Models;");
                snippet.AppendLine("using System.CodeDom.Compiler;");
                snippet.AppendLine("using Microsoft.CSharp;");
                snippet.AppendLine("using System.Text;");
                snippet.AppendLine("public class DynoFuncLibrary");
                snippet.AppendLine("{");
                foreach (FuncLibrary func in funcs)
                {
                    snippet.AppendLine(func.CodeExec);
                }

                snippet.AppendLine("}");

                CompilerResults cresult = CompileScript(snippet.ToString());
            }

            return View();
        }

        public ActionResult Card()
        {
            string pageName = "User";
            string userId = "";
            bool isnew = true;
            if (Request.QueryString.AllKeys.Count() > 0)
            {
                userId = Request.QueryString["userid"];
                isnew = false;
            }

            CardPage cardPage = new CardPage();
            using (DynoDataContext dataContext = new DynoDataContext())
            {
                List<AppObject> appObjects = dataContext.AppObjects.Where(obj => (obj.Name == pageName && obj.PageType == "CARD")).ToList();
                if (appObjects.Count > 0)
                {
                    string formXml = appObjects[0].Metadata;
                    cardPage = Utility.DeserializeString<CardPage>(formXml) as CardPage;

                    List<AppObject> linkedTables = dataContext.AppObjects.Where(obj => (obj.Name == appObjects[0].LinkTable)).ToList();
                    string tableXml = linkedTables[0].Metadata;
                    AppTable appTable = Utility.DeserializeString<AppTable>(tableXml) as AppTable;
                    List<AppTableField> selectFields = appTable.Fields.Where(obj => (obj.DataType == "select")).ToList();
                    foreach (AppTableField tableField in selectFields)
                    {
                        List<CardPageFieldsField> cardSelectFields = cardPage.Fields.Field.Where(obj => (obj.Name == tableField.Name)).ToList();
                        if (cardSelectFields.Count > 0)
                        {
                            cardSelectFields[0].Options = tableField.Options;
                        }
                    }

                    if (!isnew)
                    {
                        string selectQuery = Record.GetSqlSelectStatement(linkedTables[0].Name, cardPage.Fields.Field, string.Format("[UserID]='{0}'", userId));
                        DataSet resultSet = DataAccess.RunSelectStatement(selectQuery);
                        if (resultSet.Tables.Count > 0)
                        {
                            if (resultSet.Tables[0].Rows.Count > 0)
                            {
                                DataRow record = resultSet.Tables[0].Rows[0];
                                foreach (CardPageFieldsField field in cardPage.Fields.Field)
                                {
                                    field.Value = record[field.Name].ToString();
                                }
                            }
                        }
                    }
                }
            }

            return View(cardPage);
        }

        public ActionResult List()
        {
            string pageName = "User";

            ListPage listPage = new ListPage();
            ListModel model = new ListModel();
            using (DynoDataContext dataContext = new DynoDataContext())
            {
                List<AppObject> appObjects = dataContext.AppObjects.Where(obj => (obj.Name == pageName && obj.PageType == "LIST")).ToList();
                if (appObjects.Count > 0)
                {
                    string formXml = appObjects[0].Metadata;
                    listPage = Utility.DeserializeString<ListPage>(formXml) as ListPage;

                    List<AppObject> linkedTables = dataContext.AppObjects.Where(obj => (obj.Name == appObjects[0].LinkTable)).ToList();
                    string tableXml = linkedTables[0].Metadata;
                    AppTable appTable = Utility.DeserializeString<AppTable>(tableXml) as AppTable;

                    string selectQuery = Record.GetSqlSelectStatement(linkedTables[0].Name, listPage);
                    DataSet resultSet = DataAccess.RunSelectStatement(selectQuery);
                    if (resultSet.Tables.Count > 0)
                    {
                        model.RecordTable = resultSet.Tables[0];
                    }

                    model.TableColumns = appTable.Fields.ToList();
                    model.PageColumns = listPage.Fields.ToList();
                }
            }

            return View(model);
        }

        [HttpPost]
        public ActionResult Card(CardPage model)
        {
            ContextData = new Dictionary<string, string>();

            string pageName = "User";
            string userId = "";
            bool isnew = true;
            if (Request.QueryString.AllKeys.Contains("userid"))
            {
                userId = Request.QueryString["userid"];
                isnew = false;
            }

            CardPage cardPage = new CardPage();
            using (DynoDataContext dataContext = new DynoDataContext())
            {
                List<AppObject> appObjects = dataContext.AppObjects.Where(obj => (obj.Name == pageName && obj.PageType == "CARD")).ToList();
                if (appObjects.Count > 0)
                {
                    string formXml = appObjects[0].Metadata;
                    cardPage = Utility.DeserializeString<CardPage>(formXml) as CardPage;

                    List<AppObject> linkedTables = dataContext.AppObjects.Where(obj => (obj.Name == appObjects[0].LinkTable)).ToList();
                    string tableXml = linkedTables[0].Metadata;
                    AppTable appTable = Utility.DeserializeString<AppTable>(tableXml) as AppTable;
                    List<AppTableField> selectFields = appTable.Fields.Where(obj => (obj.DataType == "select")).ToList();
                    foreach (AppTableField tableField in selectFields)
                    {
                        List<CardPageFieldsField> cardSelectFields = cardPage.Fields.Field.Where(obj => (obj.Name == tableField.Name)).ToList();
                        if (cardSelectFields.Count > 0)
                        {
                            cardSelectFields[0].Options = tableField.Options;
                        }
                    }

                    foreach (CardPageFieldsField field in cardPage.Fields.Field)
                    {
                        if (Request.Form.AllKeys.Contains(field.Name))
                        {
                            if (field.DataType == "checkbox")
                            {
                                string value = "false";
                                if (Request.Form[field.Name] == "on")
                                {
                                    value = "true";
                                }

                                field.Value = value;
                            }
                            else
                            {
                                field.Value = Request.Form[field.Name];
                            }

                            ContextData.Add(field.Name, field.Value);
                        }
                    }

                    RunCustCode(Request.Form["callfunc"]);
                    //if (isnew)
                    //{
                    //    string insertQuery = GetSqlInsertStatement(linkedTables[0].Name, cardPage.Fields);
                    //    DataAccess.ExecuteNonQuery(insertQuery);
                    //}
                    //else
                    //{
                    //    string updateQuery = GetSqlUpdateStatement(linkedTables[0].Name, cardPage.Fields, string.Format("[UserID]='{0}'", userId));
                    //    DataAccess.ExecuteNonQuery(updateQuery);
                    //}
                }
            }

            return View(cardPage);
        }

        private string RunCustCode(string method)
        {
            string result = "";
            Assembly funcLib = Assembly.LoadFile(@"E:\codeplex\FlexiMax\DynamicForm\DynamicForm\bin\DynoFuncLibrary.dll");
            Type type = funcLib.GetType("DynoFuncLibrary");
            if (type != null)
            {
                MethodInfo methodInfo = type.GetMethod(method.Replace("FuncLib@", ""));
                if (methodInfo != null)
                {
                    List<object> parameters = new List<object>();
                    parameters.Add(ContextData);
                    methodInfo.Invoke(methodInfo, parameters.ToArray());
                }
            }

            //string[] splitStr = method.Split('.');

            //using (DynoDataContext dataContext = new DynoDataContext())
            //{
            //    List<AppObject> appObjects = dataContext.AppObjects.Where(obj => (obj.Name == splitStr[0] && obj.PageType == "CLASS")).ToList();
            //    if (appObjects.Count > 0)
            //    {
            //        string formXml = appObjects[0].Metadata;
            //        DynoClass dynoClass = Utility.DeserializeString<DynoClass>(formXml) as DynoClass;
            //        List<DynoClassMethod> methods = dynoClass.Method.Where(obj => (obj.Name == splitStr[1])).ToList();
            //        if (methods.Count > 0)
            //        {
            //            StringBuilder snippet = new StringBuilder();
                        
            //            snippet.AppendLine(string.Format("public class Cls{0}", appObjects[0].Name));
            //            snippet.AppendLine("{");
            //            snippet.AppendLine(string.Format("    public static {0} {1}(Dictionary<string, string> ContextData)", methods[0].OutputVariable.DataType, methods[0].Name));
            //            snippet.AppendLine("    {");
            //            if (methods[0].OutputVariable != null)
            //            {
            //                snippet.AppendLine(string.Format("{0} {1};", methods[0].OutputVariable.DataType, methods[0].OutputVariable.Name));
            //            }

            //            snippet.AppendLine(methods[0].CodeExec);
            //            snippet.AppendLine("    }");
            //            snippet.AppendLine("}");

            //            CompilerResults cresult = CompileScript(snippet.ToString());
            //        }
            //    }
            //}

            return result;
        }

        public CompilerResults CompileScript(string source)
        {
            List<string> assemblies = new List<string>();
            assemblies.Add("System.dll");
            assemblies.Add("System.Data.dll");
            assemblies.Add("System.Data.Linq.dll");
            assemblies.Add(@"E:\codeplex\FlexiMax\DynamicForm\DynamicForm\bin\DynamicForm.dll");
            CompilerParameters parms = new CompilerParameters(assemblies.ToArray());
            parms.GenerateExecutable = false;
            parms.GenerateInMemory = false;
            parms.IncludeDebugInformation = false;
            parms.OutputAssembly = @"E:\codeplex\FlexiMax\DynamicForm\DynamicForm\bin\DynoFuncLibrary.dll";

            CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");

            return compiler.CompileAssemblyFromSource(parms, source);
        } 
    }
}
